package mynl

import (
	"fmt"
)

////////////////////////////////////////////////////////////////////////////////
//Parser

/**
 * 语法解析器。
 * 通常用parseProg()作为入口，解析整个程序。也可以用下级的某个节点作为入口，只解析一部分语法。
 */
type Parser struct {
	tokenizer Tokenizer
}

func NewParser(tokenizer Tokenizer) *Parser {
	return &Parser{
		tokenizer: tokenizer,
	}
}

/**
 * 解析Prog
 * 语法规则：
 * prog = (functionDecl | functionCall)*
 */
func (selfx *Parser) ParseProg() *Prog {
	var stmts []IStatement
	var stmt IStatement
	var token = selfx.tokenizer.peek()

	//每次循环解析一个语句
	for {
		if token.Kind == TokenKind_EOF {
			break
		}

		if token.Kind == TokenKind_Keyword && token.Text == "function" {
			//先尝试一下函数声明
			stmt = selfx.parseFunctionDecl()

			if stmt != nil {
				//读取成功压入stmts
				stmts = append(stmts, stmt)
				fmt.Println("FunctionDecl added!")
			} else {
				//读取失败
				fmt.Println("parseFunctionDecl failed!!!")
			}

		} else if token.Kind == TokenKind_Identifier {
			//再尝试一下函数调用
			stmt = selfx.parseFunctionCall()

			if stmt != nil {
				//读取成功压入stmts
				stmts = append(stmts, stmt)
				fmt.Println("FunctionCall added!")
			} else {
				//读取失败
				fmt.Println("parseFunctionCall failed!!!")
			}
		} else {
			fmt.Println("neither parseFunctionDecl nor parseFunctionCall!!!")
		}

		//下一个token
		token = selfx.tokenizer.peek()
	}

	return newProg(stmts)
}

/**
 * 解析函数声明
 * 语法规则：
 * functionDecl: "function" Identifier "(" ")"  functionBody
 */
func (selfx *Parser) parseFunctionDecl() *FunctionDecl {
	var oldPos int = selfx.tokenizer.position()
	var t Token = selfx.tokenizer.next()

	if t.Kind == TokenKind_Keyword && t.Text == "function" {
		t = selfx.tokenizer.next()
		if t.Kind == TokenKind_Identifier {
			//读取"("和")"
			var t1 = selfx.tokenizer.next()
			if t1.Text == "(" {
				var t2 = selfx.tokenizer.next()
				if t2.Text == ")" {
					//尝试读取FunctionBody
					var functionBody = selfx.parseFunctionBody()
					if isFunctionBodyNode(functionBody) {
						fmt.Println("parseFunctionBody successed!")

						//如果解析成功，从这里返回
						return newFunctionDecl(t.Text, functionBody)
					} else {
						fmt.Println("Error parsing FunctionBody in FunctionDecl")
						return nil
					}
				} else {
					//括号不匹配
					fmt.Println("Expecting ')' in FunctionDecl, while we got a " + t.Text)
					return nil
				}
			} else {
				//函数声明格式不正确
				fmt.Println("Expecting '(' in FunctionDecl, while we got a " + t.Text)
				return nil
			}
		}
	}

	//如果解析不成功，回溯，返回nil。
	selfx.tokenizer.traceBack(oldPos)
	fmt.Println("parseFunctionDecl traceBack!")
	return nil
}

/**
 * 解析函数体
 * 语法规则：
 * functionBody : '{' functionCall* '}'
 */
func (selfx *Parser) parseFunctionBody() *FunctionBody {
	var oldPos int = selfx.tokenizer.position()
	var stmts []FunctionCall
	var t Token = selfx.tokenizer.next()

	if t.Text == "{" {
		//从函数中读取一个个的FunctionCall
		var functionCall = selfx.parseFunctionCall()
		for {
			//解析函数体
			if !isFunctionCallNode(functionCall) {
				break
			}

			stmts = append(stmts, *functionCall)
			functionCall = selfx.parseFunctionCall()
		}

		t = selfx.tokenizer.next()
		if t.Text == "}" {
			//FunctionBody读取结束
			return newFunctionBody(stmts)
		} else {
			//花括号不匹配
			fmt.Println("Expecting '}' in FunctionBody, while we got a " + t.Text)
		}
	} else {
		//FunctionBody格式错误
		fmt.Println("Expecting '{' in FunctionBody, while we got a " + t.Text)
	}

	//如果解析不成功，回溯，返回nil。
	fmt.Println("parseFunctionBody traceBack!")
	selfx.tokenizer.traceBack(oldPos)
	return nil
}

/**
 * 解析函数调用
 * 语法规则：
 * functionCall : Identifier '(' parameterList? ')'
 * parameterList : StringLiteral (',' StringLiteral)*
 */
func (selfx *Parser) parseFunctionCall() *FunctionCall {
	var oldPos int = selfx.tokenizer.position()
	var params []string
	var t Token = selfx.tokenizer.next()

	if t.Kind == TokenKind_Identifier {
		var t1 Token = selfx.tokenizer.next()
		if t1.Text == "(" {
			var t2 Token = selfx.tokenizer.next()
			//循环，读出所有参数
			for {
				if t2.Text == ")" {
					break
				}

				if t2.Kind == TokenKind_StringLiteral {
					//字符串参数
					params = append(params, t2.Text)
				} else {
					//暂不支持其他类型参数
					fmt.Println("Expecting parameter in FunctionCall, while we got a " + t2.Text)
					return nil //出错时，就不在错误处回溯了。
				}

				t2 = selfx.tokenizer.next()
				//参数部分未结束，分析其他参数
				if t2.Text != ")" {
					if t2.Text == "," {
						//其他参数
						t2 = selfx.tokenizer.next()
					} else {
						//格式错误
						fmt.Println("Expecting a comma in FunctionCall, while we got a " + t2.Text)
						return nil
					}
				}
			}

			//参数获取完毕
			t2 = selfx.tokenizer.next()
			if t2.Text == ";" {
				//消化掉一个分号：
				fmt.Println("parseFunctionCall successed!")
				return newFunctionCall(t.Text, params)
			} else {
				//格式错误
				fmt.Println("Expecting a semicolon in FunctionCall, while we got a " + t2.Text)
			}
		}
	}

	//如果解析不成功，回溯，返回nil。
	fmt.Println("parseFunctionCall traceBack!")
	selfx.tokenizer.traceBack(oldPos)
	return nil
}
